package com.china08.yxyapi.config;

import org.pac4j.core.authorization.authorizer.CheckProfileTypeAuthorizer;
import org.pac4j.core.authorization.authorizer.RequireAnyRoleAuthorizer;
import org.pac4j.core.client.Clients;
import org.pac4j.core.config.Config;
import org.pac4j.core.context.HttpConstants;
import org.pac4j.core.profile.CommonProfile;
import org.pac4j.http.client.direct.HeaderClient;
import org.pac4j.http.client.direct.ParameterClient;
import org.pac4j.jwt.config.encryption.SecretEncryptionConfiguration;
import org.pac4j.jwt.config.signature.SecretSignatureConfiguration;
import org.pac4j.jwt.credentials.authenticator.JwtAuthenticator;
import org.pac4j.jwt.profile.JwtGenerator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.china08.yxyapi.security.authorizer.CurrentRoleIdAuthorizer;
import com.china08.yxyapi.security.authorizer.CustomAuthorizer;
import com.china08.yxyapi.security.profile.YxyProfile;

/**
 * Pac4j Config
 * 
 * @author Ertao.Fang
 *
 */
@Configuration
public class Pac4jConfig {

    @Value("${salt}")
    private String salt;

    @Bean
    SecretSignatureConfiguration secretSignatureConfiguration() {
        SecretSignatureConfiguration configuration = new SecretSignatureConfiguration(salt);
        return configuration;
    }

    @Bean
    SecretEncryptionConfiguration secretEncryptionConfiguration() {
        SecretEncryptionConfiguration configuration = new SecretEncryptionConfiguration(salt);
        return configuration;
    }

    @Bean
    JwtGenerator<CommonProfile> jwtGenerator() {
        JwtGenerator<CommonProfile> generator = new JwtGenerator<CommonProfile>();
        generator.setSignatureConfiguration(secretSignatureConfiguration());
        generator.setEncryptionConfiguration(secretEncryptionConfiguration());
        return generator;
    }

    @Bean
    @SuppressWarnings("unchecked")
    public Config config() {

        // REST authent with JWT for a token passed in the url as the token
        // parameter
        final SecretSignatureConfiguration secretSignatureConfiguration = new SecretSignatureConfiguration(salt);
        final SecretEncryptionConfiguration secretEncryptionConfiguration = new SecretEncryptionConfiguration(salt);
        final JwtAuthenticator authenticator = new JwtAuthenticator();
        authenticator.setSignatureConfiguration(secretSignatureConfiguration);
        authenticator.setEncryptionConfiguration(secretEncryptionConfiguration);

        // Parameter Client
        ParameterClient parameterClient = new ParameterClient("token", authenticator);
        parameterClient.setSupportGetRequest(true);
        parameterClient.setSupportPostRequest(true);

        // Header Client
        // HeaderClient headerClient = new
        // HeaderClient(HttpConstants.AUTHORIZATION_HEADER,
        // HttpConstants.BEARER_HEADER_PREFIX, authenticator);
        HeaderClient headerClient = new HeaderClient(HttpConstants.AUTHORIZATION_HEADER, "Bearer ", authenticator);

        // Clients
        final Clients clients = new Clients("https://localhost:8080/callback", //
                parameterClient, //
                headerClient);

        // Conifg
        final Config config = new Config(clients);
        config.addAuthorizer("admin", new RequireAnyRoleAuthorizer<CommonProfile>("ROLE_ADMIN"));
        config.addAuthorizer("custom", new CustomAuthorizer());
        config.addAuthorizer("profile", new CheckProfileTypeAuthorizer<CommonProfile>(CommonProfile.class));
        // ##
        // 平台角色:教师,学生,家长
        config.addAuthorizer("teacher", new CurrentRoleIdAuthorizer<YxyProfile>("ROLE_TEACHER"));
        config.addAuthorizer("student", new CurrentRoleIdAuthorizer<YxyProfile>("ROLE_STUDENT"));
        config.addAuthorizer("parents", new CurrentRoleIdAuthorizer<YxyProfile>("ROLE_PARENTS"));

        // 平台角色:教育局管理员,学校管理员
        config.addAuthorizer("eduadmin", new CurrentRoleIdAuthorizer<YxyProfile>("ROLE_EDU_ADMIN"));
        config.addAuthorizer("schadmin", new CurrentRoleIdAuthorizer<YxyProfile>("ROLE_SCH_ADMIN"));
        // config.addMatcher(name, matcher);
        return config;
    }
}
